<?php

namespace api\mobile;

use app\common\model\Mobile;
use think\facade\Db;

/**
 * 万图.
 *
 * 后台地址 https://api.nyyun.cn/admin/
 * 接口地址 https://api.nyyun.cn
 */
class Nianyu extends BaseModel
{
    private $urlHost = 'jj.dmjvip.com';
    private $header = [
        'Content-Type: multipart/form-data',
    ];

    /**
     * 创建订单.
     *
     * @params
     * sub_order_id 系统订单号
     * amount 充值金额
     * mobile 充值号码
     *
     * $return  false/供应商订单号
     */
    public function create($order)
    {
        if ($order['order_type'] == 1) {
            // 慢充
            $url = $this->info['url'] . '/api/rechargeslow/server';
        } else {
            // 快充
            $url = $this->info['url'] . '/api/recharge/server';
        }
        $params = [
            'appId' => $this->info['app_id'],
            'mobile' => $order['mobile'],
            'orderId' => $order['sub_order_id'],
            'amount' => fen2yuan($order['amount']),
            'notifyUrl' => $this->notifyUrl,
            'urlHost' => $this->urlHost,
            'timestamp' => time(),
        ];
        $params['sign'] = $this->getSign($params);
        $res = curlPost($url, $params, $this->header, 40, true);
        $res = json_decode($res, true);

        $supplier_order_no = '';
        $returnCode = $res['return_code'] ?? 400;
        $remark = $res['return_msg'] ?? '下单失败';
        switch ($returnCode) {
            case 200:  // 受理成功
                $status = self::SUCCESS;
                $supplier_order_no = $res['data']['number'];
                break;
            case 208:  // 商家平台账户余额不能低于 200 元
                $status = self::LACK_OF_MONEY;
                break;
            case 201:  // 查询订单不存在
            case 202:  // 签名错误
            case 203:  // 缺少参数
            case 204:  // appId 不正确
            case 206:  // 请先绑定域名
            case 207:  // 绑定的域名不正确
            case 209:  //（快充） 充值金额必须是 30/50/100/200
            case 209:  //（慢充） 充值金额必须是 50/100/200 元
            case 211:  // 受理失败
            case 212:  // 快充接口权限不足
            case 213:  // 慢充接口权限不足
            case 225:  // 手机格式不正确
            case 240:  // 平台暂未配置权限
            case 262:  // 手机号当日充值超限（每个手机每天最多提交3次， 包括充值失败和成功）
            case 1111: // 快充移动运营商维护中
            case 1112: // 快充联通运营商维护中
            case 1113: // 快充电信运营商维护中
            case 1121: // 慢充移动运营商维护中
            case 1122: // 慢充联通运营商维护中
            case 1123: // 慢充电信运营商维护中
                $status = self::FAIL;
                break;
            case 220:  // 转网手机号，无法充值
            case 221:  // 虚拟手机号，无法充值
            case 222:  // 手机号码不支持
            case 223:  // 手机号为空号，无法充值
                $status = self::RECHARGE_FAIL;
                break;
            case 400:  // 请求失败，其它未知原因
            case 410:  // 接口超出请求频率
                $status = self::NEED_RETRY;
                break;
            case 261:  // 商家订单号已存在
            default:
                $status = self::NEED_CONFIRM;
                break;
        }

        return compact('status', 'supplier_order_no', 'remark');
    }

    /**
     * 查询余额.
     *
     * 单位：分
     */
    public function queryAmount()
    {
        $url = $this->info['url'] . '/api/amount/server';
        $params = [
            'appId' => $this->info['app_id'],
            'urlHost' => $this->urlHost,
            'timestamp' => time(),
        ];
        $params['sign'] = $this->getSign($params);
        $res = curlPost($url, $params, $this->header);
        $res = json_decode($res, true);
        if (!isset($res['data']['amount_balance'])) {
            $this->error = $res['return_msg'] ?? '查询频繁';

            return false;
        }

        return yuan2fen($res['data']['amount_balance']);
    }

    /**
     * 订单查询.
     */
    public function query($orderId)
    {
        $url = $this->info['url'] . '/api/order/searchorderpay';
        $params = [
            'orderId' => $orderId,
        ];
        $res = curlPost($url, $params, $this->header);
        $res = json_decode($res, true);

        return $res;
    }

    /**
     * 查询运营商维护状态.
     */
    public function getIspStatus()
    {
        $url = $this->info['url'] . '/openapi/phone/get_isp_status';
        $params = [
            'appId' => $this->info['app_id'],
            'timestamp' => time(),
        ];
        $params['sign'] = $this->getSign($params);
        $res = curlPost($url, $params, $this->header);
        $res = json_decode($res, true);
        if ($res['return_code'] != 200) {
            $this->error = $res['return_msg'] ?? '查询频繁';

            return false;
        }

        return $res['data'];
    }

    /**
     * 查询三网成功率.
     *
     * isSlow 0快充 1慢充
     */
    public function getSuccessRate($isSlow = 0)
    {
        $url = $this->info['url'] . '/openapi/phone/get_success_rate';
        $params = [
            'appId' => $this->info['app_id'],
            'timestamp' => time(),
            'isSlow' => $isSlow,
        ];
        $params['sign'] = $this->getSign($params);
        $res = curlPost($url, $params, $this->header);
        $res = json_decode($res, true);
        if ($res['return_code'] != 200) {
            $this->error = $res['return_msg'] ?? '查询频繁';

            return false;
        }

        return $res['data'];
    }

    /**
     * 订单查询2.
     */
    public function searchpay($number)
    {
        $url = $this->info['url'] . '/api/order/searchpay';
        $params = [
            'number' => $number,
        ];
        $res = curlPost($url, $params, $this->header);
        $res = json_decode($res, true);

        return $res;
    }

    /**
     * 生成签名.
     */
    public function getSign($params)
    {
        if (isset($params['sign'])) {
            unset($params['sign']);
        }
        ksort($params);
        $str = '';
        foreach ($params as $k => $v) {
            if ($v !== '') {
                $str .= $k . '=' . $v . '&';
            }
        }
        $str .= 'key=' . $this->info['app_secret'];

        return strtoupper(md5($str));
    }

    /**
     * 订单回调.
     */
    public function notify($params)
    {
        $insert = [
            'sub_order_id' => $params['orderId'] ?? '',
            'params' => json_encode($params, JSON_UNESCAPED_UNICODE),
            'result' => 'SUCCESS',
        ];

        $sign = $params['sign'] ?? '';
        $checkSign = $this->getSign($params);
        if ($sign !== $checkSign) {
            $insert['result'] = '验签失败';
            Db::name('mobile_notify')->insert($insert);

            return $insert['result'];
        }

        $order = Db::name('mobile_order')
            ->where('sub_order_id', $params['orderId'])
            ->where('mobile_supplier_id', $this->info['id'])
            ->where('mobile', $params['mobile'])
            ->find();
        if (empty($order)) {
            $insert['result'] = '订单不存在';
            Db::name('mobile_notify')->insert($insert);

            return $insert['result'];
        }

        if (in_array($order['supplier_status'], [3, 4, 99])) {
            // if ($order['supplier_status'] == 3) {
            $insert['result'] = '已经成功过';
            Db::name('mobile_notify')->insert($insert);

            return 'SUCCESS';
        }

        if ($order['supplier_status'] != 2) {
            $insert['result'] = '订单状态有误：' . $order['supplier_status'];
            Db::name('mobile_notify')->insert($insert);

            return $insert['result'];
        }

        $amount = fen2yuan($order['amount']);
        if ($amount != $params['amount']) {
            $insert['result'] = '订单金额不一致：' . $amount . ' -- ' . $params['amount'];
            Db::name('mobile_notify')->insert($insert);

            return $insert['result'];
        }

        // 供应商订单状态：1订单未创建 2订单已创建 3充值成功 4充值失败
        // SUCCESS充值成功、FAIL充值失败
        $supplierStatusMap = [
            'success' => 3, // success已充值 --> 3充值成功
            // 'fail' => 4, // fail充值失败 --> 4充值失败
            'fail' => 99, // fail充值失败 --> 充值失败，等待重试
        ];
        $status = strtolower($params['status']);
        $supplierStatus = $supplierStatusMap[$status] ?? 2;
        if ($order['supplier_status'] == $supplierStatus) {
            Db::name('mobile_notify')->insert($insert);

            return 'SUCCESS';
        }
        $update = [
            'supplier_order_no' => $params['number'],
            'supplier_status' => $supplierStatus,
        ];
        if ($supplierStatus == 99) {
            // $update['refund_status'] = 2;   // 充值失败，退款
            $order['notify_url'] = '';  // 失败通知先不发
        }
        if (!empty($params['createdAt'])) {
            $update['finish_time'] = strtotime($params['createdAt']);
        }

        Db::name('mobile_notify')->insert($insert);

        Db::startTrans();
        try {
            // 如果是返佣模式，将订单结算方式改成待结算
            if ($supplierStatus == 3 && $order['settle_type'] == SETTLE_TYPE_PROFIT) {
                if ($order['profit'] == 0) {
                    $update['settle_status'] = 3;
                } elseif ($order['settle_status'] == 1) {
                    $update['settle_status'] = 2;
                }
            }

            Mobile::handleNotify($order, $update);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            $insert['result'] = '订单更新失败' . $order['id'] . '。' . $e->getMessage();
            Db::name('mobile_notify')->insert($insert);

            return $insert['result'];
        }

        return 'SUCCESS';
    }
}
